package mapeo;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;

import entidades.Documento;

public class MapDocumento  implements IBaseDatos{
	
	private Session session;
	private Transaction transaction;
	private Documento doc;
	
	public static final int CODIGO_ERROR = -1;
	
	public MapDocumento(){
		session = null;
		doc = new Documento();
	}
	
	public Object save(Object objGuardar){
		try{
			doc = (Documento) objGuardar;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Documento");
			return CODIGO_ERROR;
		}
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		int extensionId = CODIGO_ERROR;
		try {
			transaction = session.beginTransaction();
			extensionId = (Integer) session.save(doc);			
			transaction.commit();
		} catch (HibernateException e) {
			System.out.println("ERROR: Hibernate no puede realizar el grabado del Documento");
			transaction.rollback();
			extensionId = CODIGO_ERROR;
		} 
		finally {
			session.close();
		}
		return extensionId;
	}
	
	public boolean update(Object actualizado){
		Documento aux;
		try{
			aux= (Documento) actualizado;
		}catch (ClassCastException e){
			System.out.println("ERROR: Error en el casteo de parametros");
			return false;
		}	
		boolean flag = true;
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			doc = aux;
			session.update(doc);
			transaction.commit();
			} 
		catch (	HibernateException e) {
			transaction.rollback();
			System.out.println("ERROR: Hibernate no puede realizar la actualizacion del Documento");
			flag = false;
		} 
		finally {
			session.close();
		}
		return flag;
	}
	
	public boolean delete(Object primaryKey){
		int key;
		try{
			key= (Integer) primaryKey;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Integer");
			return false;
		}
		boolean flag= true; 
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			doc = (Documento) session.get( Documento.class, key );
			if (doc == null){
				return false;
			}
			session.delete(doc);
			transaction.commit();
		} 
		catch (HibernateException e) {
			transaction.rollback();
			System.out.println("ERROR: Hibernate no puede realizar el borrado del Documento");
			flag = false;
			} 
		finally {
			session.close();
			}
		return flag;
	}

	
	@Override
	public Object get(Object primaryKey) {
		int key;
		try{
			key = (Integer) primaryKey;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Integer");
			return null;
		}
		doc = null;
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			doc = (Documento) session.get( Documento.class, key );
			} 
		catch (	HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener el Documento");
			return null;
		} 
		finally {
			session.close();
		}
		return doc;
	}

	/**
	 * Debido a que id es una clave artificial, se usa este metodo para devolverla en base a los elementos que representan un documento
	 * @param aBuscar documento que se desea recuperar el id
	 * @return: id del documento
	 */
	@SuppressWarnings("unchecked")
	public int getId( Object aBuscar ){
		Documento docAux;
		try{
			docAux = (Documento) aBuscar;
		}catch(ClassCastException e){
			System.out.println("ERROR: No se puede castear el objeto a Documento");
			return CODIGO_ERROR;
		}
		int idDoc = CODIGO_ERROR;
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try {
			transaction = session.beginTransaction();
			List<Documento> listResultado = session.createCriteria(Documento.class)
				    .add( Restrictions.like("ubicacion", docAux.getUbicacion()) )
				    .add( Restrictions.like("nombre", docAux.getNombre()) )
				    .add( Restrictions.like("extension", docAux.getExtension()) )
				    .list();
			Iterator<Documento> iterador = listResultado.listIterator(); //En teoria es uno solo
				while( iterador.hasNext() ) {
		          doc = (Documento) iterador.next();
		          idDoc = doc.getId();
		          }
			} 
		catch (HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener el Documento");
			return CODIGO_ERROR;
		} 
		finally {
			session.close();
		}
		return idDoc;
	}
	
	/**
	 * Recorre la base de datos en busca de todas los documentos que tiene grabadas
	 * @return una lista con todas los documentos del sistema.
	 */
	@SuppressWarnings("unchecked")
	public ArrayList<Documento> obtenerDocumentosSistema(){
		session = HibernateUtil.getSessionFactory().openSession();
		ArrayList<Documento> documentos = new ArrayList<Documento>();
		try {
			 documentos = (ArrayList<Documento>) session.createCriteria(Documento.class).addOrder(Order.asc("id")).list();
			} 
		catch (	HibernateException e) {
			System.out.println("ERROR: Hibernate no puede obtener los Documentos almacenados en el sistema");
			return null;
		} 
		finally {
			session.close();
		}
		return documentos;
	}

	@Override
	public boolean deleteAll() {
		session = HibernateUtil.getSessionFactory().openSession();
		transaction = null;
		try{
			String hql = "delete from Documento";
			Query query = session.createQuery(hql);
			transaction = session.beginTransaction();
			query.executeUpdate();
			transaction.commit();
		}catch ( HibernateException e){
			System.out.println("ERROR: Hibernate no puede borrar todos los Documentos");
			transaction.rollback();
			return false;
		}
		finally{
			session.close();
		}
		return true;
	}
}
